(ns util.vector-arithmetic)

(defn scalar-product [vec_1 vec_2]
  "(scalar-product vec_1 vec_2) creates a scalar product on the basis of the passed vectors."
 (reduce + (map * vec_1 vec_2)))

(defn save-scalar-product [vec_1 vec_2]
  {:pre [(vector? vec_1) (vector? vec_2) (= (count vec_1) (count vec_2))]}
  "(save-scalar-product vec_1 vec_2) creates a scalar product on the basis of the passed vectors and verifies whether both parameters are vectors of the same size."
 (scalar-product vec_1 vec_2))

(defn scalar-product-Map 
  ([vec_1 vec_2]
    "(scalar-product-Map vec_1 vec_2) creates a scalar product on the basis of the passed maps."
  (reduce  #(+ %1 (* 
                    (get vec_1 %2) 
                    (get vec_2 %2))) 
           0  
           (set (clojure.set/union (keys vec_1) (keys vec_2)))))
  
  ([vec_1 vec_2 func_1 func_2]
    "(scalar-product-Map vec_1 vec_2 func_1 func_2) creates a scalar product on the basis of the passed maps and uses the passed functions if a key of the map cannot be retrieved.."
    (reduce  #(+ %1 (* 
                      (get vec_1 %1 (func_1 %2)) 
                   (get vec_2 %1 (func_2 %2)))) 
             0  
             (set (clojure.set/union (keys vec_1) (keys vec_2))))))

(defn save-scalar-product-Map 
  ([vec_1 vec_2]
    {:pre [(map? vec_1) (map? vec_2) (= (keys vec_1) (keys vec_2))]}
    "(save-scalar-product-Map vec_1 vec_2) creates a scalar product on the basis of the passed maps and verifies whether both parameters are maps and that both maps have the same keys."
    (scalar-product-Map vec_1 vec_2))
  
  ([vec_1 vec_2 func_1 func_2]
    {:pre [(map? vec_1) (map? vec_2) (fn? func_1) (fn? func_2)]}
    "(save-scalar-product-Map vec_1 vec_2 func_1 func_2) creates a scalar product on the basis of the passed maps and verifies whether both parameters are maps and if the passed retrieve functions are functions."
    (scalar-product-Map vec_1 vec_2 func_1 func_2)))